package name.zeno.qrcode.library

import android.annotation.SuppressLint
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import name.zeno.qrcode.library.PictureUtils.getDataColumn
import name.zeno.qrcode.library.PictureUtils.getPath
import name.zeno.qrcode.library.PictureUtils.getUriType

/**
 * - 获取图片 path  [getPath] , [getUriType] ,[getDataColumn]
 *
 * @author 陈治谋 (513500085@qq.com)
 * @since 16/3/1
 */
internal object PictureUtils {

  object UriType {
    val TYPES = arrayOf("com.android.externalstorage.documents", "com.android.providers.downloads.documents", "com.android.providers.media.documents", "com.google.android.apps.photos.content")

    val EXTERNAL_STORAGE_DOCUMENT = 0
    val DOWNLOADS_DOCUMENT = 1
    val MEDIA_DOCUMENT = 2
    val GOOGLE_PHOTOS_RUI = 3
    val UNKNOWN = 4
  }

  /**
   * @param uri 图片uri
   */
  fun getPath(context: Context, uri: Uri): String? {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
      // DocumentProvider

      val docId: String
      val split: Array<String>
      val type: String
      var contentUri: Uri?

      when (getUriType(uri)) {
        UriType.EXTERNAL_STORAGE_DOCUMENT -> {
          // ExternalStorageProvider
          docId = DocumentsContract.getDocumentId(uri)
          split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
          type = split[0]

          if ("primary".equals(type, ignoreCase = true)) {
            return (Environment.getExternalStorageDirectory().toString() + "/"
                + split[1])
          }
        }
        UriType.DOWNLOADS_DOCUMENT -> {
          // DownloadsProvider
          val id = DocumentsContract.getDocumentId(uri)
          contentUri = ContentUris.withAppendedId(
              Uri.parse("content://downloads/public_downloads"),
              java.lang.Long.valueOf(id)!!)
          return getDataColumn(context, contentUri, null, null)
        }
        UriType.MEDIA_DOCUMENT -> {
          // MediaProvider
          docId = DocumentsContract.getDocumentId(uri)
          split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
          type = split[0]
          contentUri = null
          if ("image" == type) {
            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
          } else if ("video" == type) {
            contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
          } else if ("audio" == type) {
            contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
          }
          val selection = "_id=?"
          val selectionArgs = arrayOf(split[1])
          return getDataColumn(context, contentUri, selection,
              selectionArgs)
        }
      }// TODO handle non-primary volumes
    } else if ("content".equals(uri.scheme, ignoreCase = true)) {
      // MediaStore (and general)

      return if (UriType.GOOGLE_PHOTOS_RUI == getUriType(uri)) {
        // Return the remote address
        uri.lastPathSegment
      } else {
        getDataColumn(context, uri, null, null)
      }
    } else if ("file".equals(uri.scheme, ignoreCase = true)) {
      // File
      return uri.path
    }

    return null
  }

  private fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {
    var cursor: Cursor? = null
    val column = "_data"
    val projection = arrayOf(column)
    try {
      cursor = context.contentResolver.query(uri!!, projection,
          selection, selectionArgs, null)
      if (cursor != null && cursor.moveToFirst()) {
        val index = cursor.getColumnIndexOrThrow(column)
        return cursor.getString(index)
      }
    } finally {
      if (cursor != null)
        cursor.close()
    }
    return null
  }

  private fun getUriType(uri: Uri): Int {
    for (i in UriType.TYPES.indices) {
      val type = UriType.TYPES[i]
      if (type == uri.authority) {
        return i
      }
    }

    return UriType.UNKNOWN
  }

}
